﻿using System;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Windows.Input;
using Elca.MvvmHelpers;

namespace ULSDeobfuscator {

    class EditComplexFilterViewModel : BaseViewModel {

        private ComplexFilter _filter;
        private bool _isExpressionOK;

        public ComplexFilter Filter {
            get { return _filter; }
            set {
                if (_filter != value) {
                    _filter = value;
                    _filter.PropertyChanged += OnFilterExpressionChanged;
                    OnPropertyChanged("Filter");
                }
            }
        }

        public string Title { get; set; }

        public ICommand OKCommand { get; private set; }
        public ICommand CancelCommand { get; private set; }
        public ICommand LoadCommand { get; private set; }

        private bool _isRegularExpression;
        public bool IsRegularExpression {
            get { return _isRegularExpression; }
            set {
                if (_isRegularExpression != value) {
                    _isRegularExpression = value;
                    OnPropertyChanged("IsRegularExpression");
                }
            }
        }

        private bool _isCaseSensitive;
        public bool IsCaseSensitive {
            get { return _isCaseSensitive; }
            set {
                if (_isCaseSensitive != value) {
                    _isCaseSensitive = value;
                    OnPropertyChanged("IsCaseSensitive");

                    UpdateMatchResult();
                }
            }
        }

        private string _testMessage;

        public string TestMessage {
            get { return _testMessage; }
            set {
                if (_testMessage != value) {
                    _testMessage = value;
                    OnPropertyChanged("TestMessage");

                    UpdateMatchResult();
                }
            }
        }

        private string _matchResult;

        public string MatchResult {
            get { return _matchResult; }
            set {
                if (_matchResult != value) {
                    _matchResult = value;
                    OnPropertyChanged("MatchResult");
                }
            }
        }

        public double WindowHeight {
            get { return App.GlobalSettings.EditComplexFilterWindowHeight; }
            set {
                if (App.GlobalSettings.EditComplexFilterWindowHeight != value) {
                    App.GlobalSettings.EditComplexFilterWindowHeight = value;
                    OnPropertyChanged("WindowHeight");
                }
            }
        }

        public double WindowWidth {
            get { return App.GlobalSettings.EditComplexFilterWindowWidth; }
            set {
                if (App.GlobalSettings.EditComplexFilterWindowWidth != value) {
                    App.GlobalSettings.EditComplexFilterWindowWidth = value;
                    OnPropertyChanged("WindowWidth");
                }
            }
        }

        public double WindowLeft {
            get { return App.GlobalSettings.EditComplexFilterWindowLeft; }
            set {
                if (App.GlobalSettings.EditComplexFilterWindowLeft != value) {
                    App.GlobalSettings.EditComplexFilterWindowLeft = value;
                    OnPropertyChanged("WindowLeft");
                }
            }
        }

        public double WindowTop {
            get { return App.GlobalSettings.EditComplexFilterWindowTop; }
            set {
                if (App.GlobalSettings.EditComplexFilterWindowTop != value) {
                    App.GlobalSettings.EditComplexFilterWindowTop = value;
                    OnPropertyChanged("WindowTop");
                }
            }
        }

        public EditComplexFilterViewModel() {

            OKCommand = new ConditionalCommand(OnOK, () => _isExpressionOK);
            CancelCommand = new ExecutableCommand(OnCancel);
            LoadCommand = new ExecutableCommand(OnLoad);

            TestMessage = "The quick brown fox jumps over the lazy dog";
        }

        private void OnLoad() {
            IsRegularExpression = _filter.IsRegex;
            IsCaseSensitive = _filter.IsCaseSensitive;
        }

        private void OnClosing() {

            _filter.PropertyChanged -= OnFilterExpressionChanged;
        }

        private void OnOK() {

            Filter.IsCaseSensitive = IsCaseSensitive;
            Filter.IsRegex = IsRegularExpression;

            OnClosing();
            RaiseCloseRequest(true);
        }

        private void OnCancel() {
            OnClosing();
            RaiseCloseRequest(false);
        }

        private void OnFilterExpressionChanged(object sender, PropertyChangedEventArgs e) {
            if (e.PropertyName == "FilterExpression") {
                UpdateMatchResult();
            }
        }

        private void UpdateMatchResult() {
            
            if (Filter == null || String.IsNullOrEmpty(Filter.FilterExpression)) {
                MatchResult = "Not applicable (please enter an expression)";
            } else if (String.IsNullOrEmpty(TestMessage)) {
                MatchResult = "Not applicable (please enter a test text)";
            } else {

                bool result;

                if (! IsRegularExpression) {
                    
                    if (IsCaseSensitive) {

                        result = TestMessage.Contains(Filter.FilterExpression);
                    } else {

                        result = TestMessage.ToLowerInvariant().Contains(Filter.FilterExpression.ToLowerInvariant());
                    }
                } else {

                    try {
                        Regex rx = new Regex(Filter.FilterExpression,
                                             IsCaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase);
                        result = rx.IsMatch(TestMessage);
                    } catch (ArgumentException) {
                        MatchResult = "N/A; please finish or correct the regular expression.";
                        _isExpressionOK = false;
                        return;
                    }
                }

                _isExpressionOK = true;
                MatchResult = result ? "The expression matches the test message." : "The expression does NOT match the test message.";
            }
        }


    }
}
